1
2
3
4 package joeq.Runtime;
5
6 import java.util.Set;
7 import java.lang.reflect.Array;
8 import java.lang.reflect.Constructor;
9 import java.lang.reflect.Field;
10 import java.lang.reflect.InvocationTargetException;
11 import java.lang.reflect.Member;
12 import java.lang.reflect.Method;
13 import java.lang.reflect.Modifier;
14 import joeq.Class.PrimordialClassLoader;
15 import joeq.Class.jq_Class;
16 import joeq.Class.jq_ClassInitializer;
17 import joeq.Class.jq_Field;
18 import joeq.Class.jq_Initializer;
19 import joeq.Class.jq_InstanceField;
20 import joeq.Class.jq_InstanceMethod;
21 import joeq.Class.jq_Member;
22 import joeq.Class.jq_Method;
23 import joeq.Class.jq_NameAndDesc;
24 import joeq.Class.jq_Primitive;
25 import joeq.Class.jq_Reference;
26 import joeq.Class.jq_StaticField;
27 import joeq.Class.jq_StaticMethod;
28 import joeq.Class.jq_Type;
29 import joeq.ClassLib.ClassLibInterface;
30 import joeq.Main.jq;
31 import joeq.Memory.Address;
32 import joeq.Memory.HeapAddress;
33 import joeq.UTF.Utf8;
34 import jwutil.util.Assert;
35 import jwutil.util.Convert;
36
37 /***
38 * @author John Whaley <jwhaley@alum.mit.edu>
39 * @version $Id: ReflectionImpl.java 2242 2005-03-21 12:39:42Z joewhaley $
40 */
41 public class ReflectionImpl implements Reflection.Delegate {
42
43 public static boolean REPORT_JDK_ERRORS = false;
44
45 public final jq_Reference getTypeOf(Object o) {
46 if (jq.RunningNative) return jq_Reference.getTypeOf(o);
47 return (jq_Reference) getJQType(o.getClass());
48 }
49
50
51 public final jq_Type getJQType(Class c) {
52 if (jq.RunningNative) return ClassLibInterface.DEFAULT.getJQType(c);
53
54 if (c.isPrimitive()) {
55 if (c == Byte.TYPE) return jq_Primitive.BYTE;
56 if (c == Character.TYPE) return jq_Primitive.CHAR;
57 if (c == Double.TYPE) return jq_Primitive.DOUBLE;
58 if (c == Float.TYPE) return jq_Primitive.FLOAT;
59 if (c == Integer.TYPE) return jq_Primitive.INT;
60 if (c == Long.TYPE) return jq_Primitive.LONG;
61 if (c == Short.TYPE) return jq_Primitive.SHORT;
62 if (c == Boolean.TYPE) return jq_Primitive.BOOLEAN;
63 if (c == Void.TYPE) return jq_Primitive.VOID;
64 Assert.UNREACHABLE(c.toString());
65 return null;
66 }
67 String className = c.getName().replace('.','/');
68 if (!className.startsWith("[")) className = "L"+className+";";
69 className = joeq.ClassLib.ClassLibInterface.convertClassLibDesc(className);
70 return PrimordialClassLoader.loader.getOrCreateBSType(className);
71 }
72 public final Class getJDKType(jq_Type c) {
73 if (jq.RunningNative) return c.getJavaLangClassObject();
74
75 if (c.getJavaLangClassObject() != null)
76 return c.getJavaLangClassObject();
77 if (c.isPrimitiveType())
78 return getJDKType((jq_Primitive)c);
79 else
80 return getJDKType((jq_Reference)c);
81 }
82 public final Class getJDKType(jq_Primitive c) {
83 if (jq.RunningNative) return c.getJavaLangClassObject();
84 if (c.getJavaLangClassObject() != null)
85 return c.getJavaLangClassObject();
86
87
88 if (c.getDesc() == Utf8.BYTE_DESC) return Byte.TYPE;
89 if (c.getDesc() == Utf8.CHAR_DESC) return Character.TYPE;
90 if (c.getDesc() == Utf8.DOUBLE_DESC) return Double.TYPE;
91 if (c.getDesc() == Utf8.FLOAT_DESC) return Float.TYPE;
92 if (c.getDesc() == Utf8.INT_DESC) return Integer.TYPE;
93 if (c.getDesc() == Utf8.LONG_DESC) return Long.TYPE;
94 if (c.getDesc() == Utf8.SHORT_DESC) return Short.TYPE;
95 if (c.getDesc() == Utf8.BOOLEAN_DESC) return Boolean.TYPE;
96 if (c.getDesc() == Utf8.VOID_DESC) return Void.TYPE;
97 Assert.UNREACHABLE(c.getName());
98 return null;
99 }
100 public Class getJDKType(jq_Reference c) {
101 if (jq.RunningNative) return c.getJavaLangClassObject();
102
103 if (c.getJavaLangClassObject() != null)
104 return c.getJavaLangClassObject();
105 try {
106 return Class.forName(c.getJDKName(), false, Reflection.class.getClassLoader());
107
108 } catch (ClassNotFoundException x) {
109 if (!c.getJDKName().startsWith("joeq.ClassLib") && !c.getJDKName().startsWith("L&"))
110 SystemInterface.debugwriteln("Note: "+c.getJDKName()+" was not found in host jdk");
111 return null;
112 }
113 }
114
115
116 public final jq_Field getJQMember(Field f) {
117 if (jq.RunningNative) return ClassLibInterface.DEFAULT.getJQField(f);
118 jq_Class c = (jq_Class)getJQType(f.getDeclaringClass());
119
120 jq_NameAndDesc nd = new jq_NameAndDesc(Utf8.get(f.getName()), getJQType(f.getType()).getDesc());
121 nd = joeq.ClassLib.ClassLibInterface.convertClassLibNameAndDesc(c, nd);
122 jq_Field m = (jq_Field)c.getDeclaredMember(nd);
123 if (m == null) {
124 if (!Utf8.NO_NEW) {
125
126 if (Modifier.isStatic(f.getModifiers()))
127 m = c.getOrCreateStaticField(nd);
128 else
129 m = c.getOrCreateInstanceField(nd);
130 }
131 }
132 return m;
133 }
134 public final jq_Method getJQMember(Method f) {
135 if (jq.RunningNative) return ClassLibInterface.DEFAULT.getJQMethod(f);
136 jq_Class c = (jq_Class)getJQType(f.getDeclaringClass());
137
138 StringBuffer desc = new StringBuffer();
139 desc.append('(');
140 Class[] param_types = f.getParameterTypes();
141 for (int i=0; i<param_types.length; ++i) {
142 desc.append(getJQType(param_types[i]).getDesc().toString());
143 }
144 desc.append(')');
145 desc.append(getJQType(f.getReturnType()).getDesc().toString());
146 jq_NameAndDesc nd = new jq_NameAndDesc(Utf8.get(f.getName()), Utf8.get(desc.toString()));
147 nd = joeq.ClassLib.ClassLibInterface.convertClassLibNameAndDesc(c, nd);
148 jq_Method m = (jq_Method)c.getDeclaredMember(nd);
149 if (m == null) {
150 if (!Utf8.NO_NEW) {
151
152 if (Modifier.isStatic(f.getModifiers()))
153 m = c.getOrCreateStaticMethod(nd);
154 else
155 m = c.getOrCreateInstanceMethod(nd);
156 }
157 }
158 return m;
159 }
160 public final jq_Initializer getJQMember(Constructor f) {
161 if (jq.RunningNative) return ClassLibInterface.DEFAULT.getJQInitializer(f);
162 jq_Class c = (jq_Class)getJQType(f.getDeclaringClass());
163
164 StringBuffer desc = new StringBuffer();
165 desc.append('(');
166 Class[] param_types = f.getParameterTypes();
167 for (int i=0; i<param_types.length; ++i) {
168 desc.append(getJQType(param_types[i]).getDesc().toString());
169 }
170 desc.append(")V");
171 jq_NameAndDesc nd = new jq_NameAndDesc(Utf8.get("<init>"), Utf8.get(desc.toString()));
172 nd = joeq.ClassLib.ClassLibInterface.convertClassLibNameAndDesc(c, nd);
173 jq_Initializer m = (jq_Initializer)c.getDeclaredMember(nd);
174 if (m == null) {
175 if (!Utf8.NO_NEW) {
176
177 m = (jq_Initializer)c.getOrCreateInstanceMethod(nd);
178 }
179 }
180 return m;
181 }
182 public boolean USE_DECLARED_FIELDS_CACHE = true;
183 private static java.util.HashMap declaredFieldsCache;
184 public final Field getJDKField(Class c, String name) {
185 Field[] fields = null;
186 if (USE_DECLARED_FIELDS_CACHE) {
187 if (declaredFieldsCache == null) declaredFieldsCache = new java.util.HashMap();
188 else fields = (Field[])declaredFieldsCache.get(c);
189 if (fields == null) {
190 try {
191 fields = c.getDeclaredFields();
192 } catch (NoClassDefFoundError x) {
193 if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
194 return null;
195 }
196 declaredFieldsCache.put(c, fields);
197 }
198 } else {
199 try {
200 fields = c.getDeclaredFields();
201 } catch (NoClassDefFoundError x) {
202 if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
203 return null;
204 }
205 }
206 for (int i=0; i<fields.length; ++i) {
207 Field f2 = fields[i];
208 if (f2.getName().equals(name)) {
209
210 return f2;
211 }
212 }
213
214 return null;
215 }
216 public boolean USE_DECLARED_METHODS_CACHE = true;
217 private static java.util.HashMap declaredMethodsCache;
218 public final Method getJDKMethod(Class c, String name, Class[] args) {
219 Method[] methods = null;
220 if (USE_DECLARED_METHODS_CACHE) {
221 if (declaredMethodsCache == null) declaredMethodsCache = new java.util.HashMap();
222 else methods = (Method[])declaredMethodsCache.get(c);
223 if (methods == null) {
224 try {
225 methods = c.getDeclaredMethods();
226 } catch (NoClassDefFoundError x) {
227 if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
228 return null;
229 }
230 declaredMethodsCache.put(c, methods);
231 }
232 } else {
233 try {
234 methods = c.getDeclaredMethods();
235 } catch (NoClassDefFoundError x) {
236 if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
237 return null;
238 }
239 }
240 uphere:
241 for (int i=0; i<methods.length; ++i) {
242 Method f2 = methods[i];
243 if (f2.getName().equals(name)) {
244 Class[] args2 = f2.getParameterTypes();
245 if (args.length != args2.length) continue uphere;
246 for (int j=0; j<args.length; ++j) {
247 if (!args[j].equals(args2[j])) continue uphere;
248 }
249
250 return f2;
251 }
252 }
253
254 return null;
255 }
256 public final Constructor getJDKConstructor(Class c, Class[] args) {
257 Constructor[] consts;
258 try {
259 consts = c.getDeclaredConstructors();
260 } catch (NoClassDefFoundError x) {
261 if (REPORT_JDK_ERRORS) SystemInterface.debugwriteln("Note: "+c+" could not be loaded in host jdk");
262 return null;
263 }
264 uphere:
265 for (int i=0; i<consts.length; ++i) {
266 Constructor f2 = consts[i];
267 Class[] args2 = f2.getParameterTypes();
268 if (args.length != args2.length) continue uphere;
269 for (int j=0; j<args.length; ++j) {
270 if (!args[j].equals(args2[j])) continue uphere;
271 }
272
273 return f2;
274 }
275
276 return null;
277 }
278 public final Member getJDKMember(jq_Member m) {
279 if (jq.RunningNative) return m.getJavaLangReflectMemberObject();
280 if (m.getJavaLangReflectMemberObject() != null)
281 return m.getJavaLangReflectMemberObject();
282 Class c = getJDKType(m.getDeclaringClass());
283 if (m instanceof jq_Field) {
284 Member ret = getJDKField(c, m.getName().toString());
285 if (ret == null) {
286
287 }
288 return ret;
289 } else if (m instanceof jq_Initializer) {
290 jq_Initializer m2 = (jq_Initializer)m;
291 jq_Type[] param_types = m2.getParamTypes();
292 int num_of_args = param_types.length-1;
293 Class[] args = new Class[num_of_args];
294 for (int i=0; i<num_of_args; ++i) {
295 args[i] = getJDKType(param_types[i+1]);
296 }
297 Member ret = getJDKConstructor(c, args);
298 if (ret == null) {
299
300 }
301 return ret;
302 } else if (m instanceof jq_ClassInitializer) {
303 return null;
304 } else {
305 Assert._assert(m instanceof jq_Method);
306 jq_Method m2 = (jq_Method)m;
307 int offset = m2.isStatic()?0:1;
308 jq_Type[] param_types = m2.getParamTypes();
309 int num_of_args = param_types.length-offset;
310 Class[] args = new Class[num_of_args];
311 for (int i=0; i<num_of_args; ++i) {
312 args[i] = getJDKType(param_types[i+offset]);
313 }
314 Member ret = getJDKMethod(c, m.getName().toString(), args);
315 if (ret == null) {
316
317 }
318 return ret;
319 }
320 }
321
322
323 public void invokestatic_V(jq_StaticMethod m) throws Throwable {
324 if (jq.RunningNative) {
325 Assert._assert(m.getDeclaringClass().isClsInitRunning());
326 Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
327 return;
328 } else {
329 Assert.UNREACHABLE();
330 }
331 }
332 public int invokestatic_I(jq_StaticMethod m) throws Throwable {
333 if (jq.RunningNative) {
334 Assert._assert(m.getDeclaringClass().isClsInitRunning());
335 return (int)Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
336 } else {
337 Assert.UNREACHABLE();
338 return 0;
339 }
340 }
341 public Object invokestatic_A(jq_StaticMethod m) throws Throwable {
342 if (jq.RunningNative) {
343 Assert._assert(m.getDeclaringClass().isClsInitRunning());
344 return ((HeapAddress)Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint())).asObject();
345 } else {
346 Assert.UNREACHABLE();
347 return null;
348 }
349 }
350 public long invokestatic_J(jq_StaticMethod m) throws Throwable {
351 if (jq.RunningNative) {
352 Assert._assert(m.getDeclaringClass().isClsInitRunning());
353 return Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
354 } else {
355 Assert.UNREACHABLE();
356 return 0L;
357 }
358 }
359 public void invokestatic_V(jq_StaticMethod m, Object arg1) throws Throwable {
360 if (jq.RunningNative) {
361 Assert._assert(m.getDeclaringClass().isClsInitRunning());
362 Unsafe.pushArgA(HeapAddress.addressOf(arg1));
363 Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
364 return;
365 } else {
366 Assert.UNREACHABLE();
367 return;
368 }
369 }
370 public void invokeinstance_V(jq_InstanceMethod m, Object dis) throws Throwable {
371 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
372 if (jq.RunningNative) {
373 Assert._assert(m.getDeclaringClass().isClsInitRunning());
374 Unsafe.pushArgA(HeapAddress.addressOf(dis));
375 Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
376 } else {
377 Assert.UNREACHABLE();
378 return;
379 }
380 }
381 public Object invokeinstance_A(jq_InstanceMethod m, Object dis) throws Throwable {
382 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
383 if (jq.RunningNative) {
384 Assert._assert(m.getDeclaringClass().isClsInitRunning());
385 Unsafe.pushArgA(HeapAddress.addressOf(dis));
386 return ((HeapAddress)Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint())).asObject();
387 } else {
388 Assert.UNREACHABLE();
389 return null;
390 }
391 }
392 public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1) throws Throwable {
393 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
394 if (jq.RunningNative) {
395 Assert._assert(m.getDeclaringClass().isClsInitRunning());
396 Unsafe.pushArgA(HeapAddress.addressOf(dis));
397 Unsafe.pushArgA(HeapAddress.addressOf(arg1));
398 Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
399 return;
400 } else {
401 Assert.UNREACHABLE();
402 return;
403 }
404 }
405 public Object invokeinstance_A(jq_InstanceMethod m, Object dis, Object arg1) throws Throwable {
406 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
407 if (jq.RunningNative) {
408 Assert._assert(m.getDeclaringClass().isClsInitRunning());
409 Unsafe.pushArgA(HeapAddress.addressOf(dis));
410 Unsafe.pushArgA(HeapAddress.addressOf(arg1));
411 return ((HeapAddress)Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint())).asObject();
412 } else {
413 Assert.UNREACHABLE();
414 return null;
415 }
416 }
417 public boolean invokeinstance_Z(jq_InstanceMethod m, Object dis, Object arg1) throws Throwable {
418 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
419 if (jq.RunningNative) {
420 Assert._assert(m.getDeclaringClass().isClsInitRunning());
421 Unsafe.pushArgA(HeapAddress.addressOf(dis));
422 Unsafe.pushArgA(HeapAddress.addressOf(arg1));
423 return ((int)Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint())) != 0;
424 } else {
425 Assert.UNREACHABLE();
426 return false;
427 }
428 }
429 public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1, Object arg2) throws Throwable {
430 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
431 if (jq.RunningNative) {
432 Assert._assert(m.getDeclaringClass().isClsInitRunning());
433 Unsafe.pushArgA(HeapAddress.addressOf(dis));
434 Unsafe.pushArgA(HeapAddress.addressOf(arg1));
435 Unsafe.pushArgA(HeapAddress.addressOf(arg2));
436 Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
437 return;
438 } else {
439 Assert.UNREACHABLE();
440 return;
441 }
442 }
443 public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1, Object arg2, Object arg3) throws Throwable {
444 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
445 if (jq.RunningNative) {
446 Assert._assert(m.getDeclaringClass().isClsInitRunning());
447 Unsafe.pushArgA(HeapAddress.addressOf(dis));
448 Unsafe.pushArgA(HeapAddress.addressOf(arg1));
449 Unsafe.pushArgA(HeapAddress.addressOf(arg2));
450 Unsafe.pushArgA(HeapAddress.addressOf(arg3));
451 Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
452 return;
453 } else {
454 Assert.UNREACHABLE();
455 return;
456 }
457 }
458 public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1, Object arg2, Object arg3, long arg4) throws Throwable {
459 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
460 if (jq.RunningNative) {
461 Assert._assert(m.getDeclaringClass().isClsInitRunning());
462 Unsafe.pushArgA(HeapAddress.addressOf(dis));
463 Unsafe.pushArgA(HeapAddress.addressOf(arg1));
464 Unsafe.pushArgA(HeapAddress.addressOf(arg2));
465 Unsafe.pushArgA(HeapAddress.addressOf(arg3));
466 Unsafe.pushArg((int)(arg4 >> 32));
467 Unsafe.pushArg((int)arg4);
468 Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
469 return;
470 } else {
471 Assert.UNREACHABLE();
472 return;
473 }
474 }
475 public void invokeinstance_V(jq_InstanceMethod m, Object dis, Object arg1, int arg2, long arg3, int arg4) throws Throwable {
476 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(dis), m.getDeclaringClass()));
477 if (jq.RunningNative) {
478 Assert._assert(m.getDeclaringClass().isClsInitRunning());
479 Unsafe.pushArgA(HeapAddress.addressOf(dis));
480 Unsafe.pushArgA(HeapAddress.addressOf(arg1));
481 Unsafe.pushArg(arg2);
482 Unsafe.pushArg((int)(arg3 >> 32));
483 Unsafe.pushArg((int)arg3);
484 Unsafe.pushArg(arg4);
485 Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
486 return;
487 } else {
488 Assert.UNREACHABLE();
489 return;
490 }
491 }
492 public long invoke(jq_Method m, Object dis, Object[] args)
493 throws IllegalArgumentException, InvocationTargetException
494 {
495 jq_Type[] params = m.getParamTypes();
496 int offset;
497 if (dis != null) {
498 Assert._assert(!m.isStatic());
499 Unsafe.pushArgA(HeapAddress.addressOf(dis));
500 offset = 1;
501 } else {
502 offset = 0;
503 }
504 if (args != null) {
505 Assert._assert(params.length == args.length+offset);
506 for (int i=0; i<args.length; ++i) {
507 jq_Type c = params[i+offset];
508 if (c.isAddressType()) {
509 Assert.TODO();
510 } else if (c.isReferenceType()) {
511 if (args[i] != null && !TypeCheck.isAssignable(jq_Reference.getTypeOf(args[i]), c))
512 throw new IllegalArgumentException(args[i].getClass()+" is not assignable to "+c);
513 Unsafe.pushArgA(HeapAddress.addressOf(args[i]));
514 } else {
515 if (c == jq_Primitive.BYTE) {
516 int v = (int)Convert.unwrapToByte(args[i]);
517 Unsafe.pushArg(v);
518 } else if (c == jq_Primitive.CHAR) {
519 int v = (int)Convert.unwrapToChar(args[i]);
520 Unsafe.pushArg(v);
521 } else if (c == jq_Primitive.DOUBLE) {
522 long v = Double.doubleToRawLongBits(Convert.unwrapToDouble(args[i]));
523 Unsafe.pushArg((int)(v >> 32));
524 Unsafe.pushArg((int)v);
525 } else if (c == jq_Primitive.FLOAT) {
526 int v = Float.floatToRawIntBits(Convert.unwrapToFloat(args[i]));
527 Unsafe.pushArg(v);
528 } else if (c == jq_Primitive.INT) {
529 int v = Convert.unwrapToInt(args[i]);
530 Unsafe.pushArg(v);
531 } else if (c == jq_Primitive.LONG) {
532 long v = Convert.unwrapToLong(args[i]);
533 Unsafe.pushArg((int)(v >> 32));
534 Unsafe.pushArg((int)v);
535 } else if (c == jq_Primitive.SHORT) {
536 int v = (int)Convert.unwrapToShort(args[i]);
537 Unsafe.pushArg(v);
538 } else if (c == jq_Primitive.BOOLEAN) {
539 int v = Convert.unwrapToBoolean(args[i])?1:0;
540 Unsafe.pushArg(v);
541 } else Assert.UNREACHABLE(c.toString());
542 }
543 }
544 } else {
545 Assert._assert(params.length == offset);
546 }
547 try {
548 return Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
549 } catch (Throwable t) {
550 throw new InvocationTargetException(t);
551 }
552 }
553 public Address invokeA(jq_Method m, Object dis, Object[] args)
554 throws IllegalArgumentException, InvocationTargetException
555 {
556 jq_Type[] params = m.getParamTypes();
557 int offset;
558 if (dis != null) {
559 Assert._assert(!m.isStatic());
560 Unsafe.pushArgA(HeapAddress.addressOf(dis));
561 offset = 1;
562 } else {
563 offset = 0;
564 }
565 if (args != null) {
566 Assert._assert(params.length == args.length+offset);
567 for (int i=0; i<args.length; ++i) {
568 jq_Type c = params[i+offset];
569 if (c.isAddressType()) {
570 Assert.TODO();
571 } else if (c.isReferenceType()) {
572 if (args[i] != null && !TypeCheck.isAssignable(jq_Reference.getTypeOf(args[i]), c))
573 throw new IllegalArgumentException(args[i].getClass()+" is not assignable to "+c);
574 Unsafe.pushArgA(HeapAddress.addressOf(args[i]));
575 } else {
576 if (c == jq_Primitive.BYTE) {
577 int v = (int)Convert.unwrapToByte(args[i]);
578 Unsafe.pushArg(v);
579 } else if (c == jq_Primitive.CHAR) {
580 int v = (int)Convert.unwrapToChar(args[i]);
581 Unsafe.pushArg(v);
582 } else if (c == jq_Primitive.DOUBLE) {
583 long v = Double.doubleToRawLongBits(Convert.unwrapToDouble(args[i]));
584 Unsafe.pushArg((int)(v >> 32));
585 Unsafe.pushArg((int)v);
586 } else if (c == jq_Primitive.FLOAT) {
587 int v = Float.floatToRawIntBits(Convert.unwrapToFloat(args[i]));
588 Unsafe.pushArg(v);
589 } else if (c == jq_Primitive.INT) {
590 int v = Convert.unwrapToInt(args[i]);
591 Unsafe.pushArg(v);
592 } else if (c == jq_Primitive.LONG) {
593 long v = Convert.unwrapToLong(args[i]);
594 Unsafe.pushArg((int)(v >> 32));
595 Unsafe.pushArg((int)v);
596 } else if (c == jq_Primitive.SHORT) {
597 int v = (int)Convert.unwrapToShort(args[i]);
598 Unsafe.pushArg(v);
599 } else if (c == jq_Primitive.BOOLEAN) {
600 int v = Convert.unwrapToBoolean(args[i])?1:0;
601 Unsafe.pushArg(v);
602 } else Assert.UNREACHABLE(c.toString());
603 }
604 }
605 } else {
606 Assert._assert(params.length == offset);
607 }
608 try {
609 return Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint());
610 } catch (Throwable t) {
611 throw new InvocationTargetException(t);
612 }
613 }
614
615 public int getfield_I(Object o, jq_InstanceField f) {
616 Assert._assert(f.getType() == jq_Primitive.INT || f.getType() == jq_Primitive.FLOAT);
617 if (!jq.RunningNative) {
618 Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
619 if (q == null) return 0;
620 return ((Integer)q).intValue();
621 }
622 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
623 return HeapAddress.addressOf(o).offset(f.getOffset()).peek4();
624 }
625 public long getfield_L(Object o, jq_InstanceField f) {
626 Assert._assert(f.getType() == jq_Primitive.LONG || f.getType() == jq_Primitive.DOUBLE);
627 if (!jq.RunningNative) {
628 Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
629 if (q == null) return 0L;
630 return ((Long)q).longValue();
631 }
632 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
633 return HeapAddress.addressOf(o).offset(f.getOffset()).peek8();
634 }
635 public float getfield_F(Object o, jq_InstanceField f) {
636 Assert._assert(f.getType() == jq_Primitive.FLOAT);
637 if (!jq.RunningNative) {
638 Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
639 if (q == null) return 0f;
640 return ((Float)q).floatValue();
641 }
642 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
643 return Float.intBitsToFloat(getfield_I(o, f));
644 }
645 public double getfield_D(Object o, jq_InstanceField f) {
646 Assert._assert(f.getType() == jq_Primitive.DOUBLE);
647 if (!jq.RunningNative) {
648 Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
649 if (q == null) return 0.;
650 return ((Double)q).doubleValue();
651 }
652 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
653 return Double.longBitsToDouble(getfield_L(o, f));
654 }
655 public Object getfield_A(Object o, jq_InstanceField f) {
656 Assert._assert(f.getType().isReferenceType());
657 Assert._assert(!f.getType().isAddressType());
658 if (!jq.RunningNative) return Reflection.obj_trav.getInstanceFieldValue(o, f);
659 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
660 return ((HeapAddress) HeapAddress.addressOf(o).offset(f.getOffset()).peek()).asObject();
661 }
662 public Address getfield_P(Object o, jq_InstanceField f) {
663 Assert._assert(f.getType().isAddressType());
664 if (!jq.RunningNative) return (Address)Reflection.obj_trav.getInstanceFieldValue(o, f);
665 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
666 return HeapAddress.addressOf(o).offset(f.getOffset()).peek();
667 }
668 public byte getfield_B(Object o, jq_InstanceField f) {
669 Assert._assert(f.getType() == jq_Primitive.BYTE);
670 if (!jq.RunningNative) {
671 Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
672 if (q == null) return 0;
673 return ((Byte)q).byteValue();
674 }
675 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
676 return HeapAddress.addressOf(o).offset(f.getOffset()).peek1();
677 }
678 public char getfield_C(Object o, jq_InstanceField f) {
679 Assert._assert(f.getType() == jq_Primitive.CHAR);
680 if (!jq.RunningNative) {
681 Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
682 if (q == null) return 0;
683 return ((Character)q).charValue();
684 }
685 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
686 return (char)HeapAddress.addressOf(o).offset(f.getOffset()).peek4();
687 }
688 public short getfield_S(Object o, jq_InstanceField f) {
689 Assert._assert(f.getType() == jq_Primitive.SHORT);
690 if (!jq.RunningNative) {
691 Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
692 if (q == null) return 0;
693 return ((Short)q).shortValue();
694 }
695 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
696 return HeapAddress.addressOf(o).offset(f.getOffset()).peek2();
697 }
698 public boolean getfield_Z(Object o, jq_InstanceField f) {
699 Assert._assert(f.getType() == jq_Primitive.BOOLEAN);
700 if (!jq.RunningNative) {
701 Object q = Reflection.obj_trav.getInstanceFieldValue(o, f);
702 if (q == null) return false;
703 return ((Boolean)q).booleanValue();
704 }
705 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
706 return HeapAddress.addressOf(o).offset(f.getOffset()).peek1()!=0;
707 }
708 public Object getfield(Object o, jq_InstanceField f) {
709 if (!jq.RunningNative) return Reflection.obj_trav.getInstanceFieldValue(o, f);
710 jq_Type t = f.getType();
711 if (t.isReferenceType()) return getfield_A(o, f);
712 if (t == jq_Primitive.INT) return new Integer(getfield_I(o, f));
713 if (t == jq_Primitive.FLOAT) return new Float(getfield_F(o, f));
714 if (t == jq_Primitive.LONG) return new Long(getfield_L(o, f));
715 if (t == jq_Primitive.DOUBLE) return new Double(getfield_D(o, f));
716 if (t == jq_Primitive.BYTE) return new Byte(getfield_B(o, f));
717 if (t == jq_Primitive.CHAR) return new Character(getfield_C(o, f));
718 if (t == jq_Primitive.SHORT) return new Short(getfield_S(o, f));
719 if (t == jq_Primitive.BOOLEAN) return Convert.getBoolean(getfield_Z(o, f));
720 Assert.UNREACHABLE();
721 return null;
722 }
723 public void putfield_I(Object o, jq_InstanceField f, int v) {
724 Assert._assert(f.getType() == jq_Primitive.INT || f.getType() == jq_Primitive.FLOAT);
725 if (!jq.RunningNative) {
726 Reflection.obj_trav.putInstanceFieldValue(o, f, new Integer(v));
727 return;
728 }
729 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
730 HeapAddress.addressOf(o).offset(f.getOffset()).poke4(v);
731 }
732 public void putfield_L(Object o, jq_InstanceField f, long v) {
733 Assert._assert(f.getType() == jq_Primitive.LONG || f.getType() == jq_Primitive.DOUBLE);
734 if (!jq.RunningNative) {
735 Reflection.obj_trav.putInstanceFieldValue(o, f, new Long(v));
736 return;
737 }
738 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
739 HeapAddress.addressOf(o).offset(f.getOffset()).poke8(v);
740 }
741 public void putfield_F(Object o, jq_InstanceField f, float v) {
742 Assert._assert(f.getType() == jq_Primitive.FLOAT);
743 if (!jq.RunningNative) {
744 Reflection.obj_trav.putInstanceFieldValue(o, f, new Float(v));
745 return;
746 }
747 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
748 putfield_I(o, f, Float.floatToRawIntBits(v));
749 }
750 public void putfield_D(Object o, jq_InstanceField f, double v) {
751 Assert._assert(f.getType() == jq_Primitive.DOUBLE);
752 if (!jq.RunningNative) {
753 Reflection.obj_trav.putInstanceFieldValue(o, f, new Double(v));
754 return;
755 }
756 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
757 putfield_L(o, f, Double.doubleToRawLongBits(v));
758 }
759 public void putfield_A(Object o, jq_InstanceField f, Object v) {
760 if (!jq.RunningNative) {
761 Reflection.obj_trav.putInstanceFieldValue(o, f, v);
762 return;
763 }
764 Assert._assert(v == null || TypeCheck.isAssignable(jq_Reference.getTypeOf(v), f.getType()));
765 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
766 HeapAddress.addressOf(o).offset(f.getOffset()).poke(HeapAddress.addressOf(v));
767 }
768 public void putfield_P(Object o, jq_InstanceField f, Address v) {
769 Assert._assert(f.getType().isAddressType());
770 if (!jq.RunningNative) {
771 Reflection.obj_trav.putInstanceFieldValue(o, f, v);
772 return;
773 }
774 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
775 HeapAddress.addressOf(o).offset(f.getOffset()).poke(v);
776 }
777 public void putfield_B(Object o, jq_InstanceField f, byte v) {
778 Assert._assert(f.getType() == jq_Primitive.BYTE);
779 if (!jq.RunningNative) {
780 Reflection.obj_trav.putInstanceFieldValue(o, f, new Byte(v));
781 return;
782 }
783 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
784 HeapAddress.addressOf(o).offset(f.getOffset()).poke1(v);
785 }
786 public void putfield_C(Object o, jq_InstanceField f, char v) {
787 Assert._assert(f.getType() == jq_Primitive.CHAR);
788 if (!jq.RunningNative) {
789 Reflection.obj_trav.putInstanceFieldValue(o, f, new Character(v));
790 return;
791 }
792 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
793 HeapAddress.addressOf(o).offset(f.getOffset()).poke2((short)((v<<16)>>16));
794 }
795 public void putfield_S(Object o, jq_InstanceField f, short v) {
796 Assert._assert(f.getType() == jq_Primitive.SHORT);
797 if (!jq.RunningNative) {
798 Reflection.obj_trav.putInstanceFieldValue(o, f, new Short(v));
799 return;
800 }
801 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
802 HeapAddress.addressOf(o).offset(f.getOffset()).poke2(v);
803 }
804 public void putfield_Z(Object o, jq_InstanceField f, boolean v) {
805 Assert._assert(f.getType() == jq_Primitive.BOOLEAN);
806 if (!jq.RunningNative) {
807 Reflection.obj_trav.putInstanceFieldValue(o, f, Convert.getBoolean(v));
808 return;
809 }
810 Assert._assert(TypeCheck.isAssignable(jq_Reference.getTypeOf(o), f.getDeclaringClass()));
811 HeapAddress.addressOf(o).offset(f.getOffset()).poke1(v?(byte)1:(byte)0);
812 }
813
814 public int getstatic_I(jq_StaticField f) {
815 Assert._assert(f.getType() == jq_Primitive.INT || f.getType() == jq_Primitive.FLOAT);
816 if (!jq.RunningNative) {
817 Object o = Reflection.obj_trav.getStaticFieldValue(f);
818 if (o == null) return 0;
819 return ((Integer)o).intValue();
820 }
821 return f.getAddress().peek4();
822 }
823 public long getstatic_L(jq_StaticField f) {
824 Assert._assert(f.getType() == jq_Primitive.LONG || f.getType() == jq_Primitive.DOUBLE);
825 if (!jq.RunningNative) {
826 Object o = Reflection.obj_trav.getStaticFieldValue(f);
827 if (o == null) return 0L;
828 return ((Long)o).longValue();
829 }
830 return f.getAddress().peek8();
831 }
832 public float getstatic_F(jq_StaticField f) {
833 Assert._assert(f.getType() == jq_Primitive.FLOAT);
834 if (!jq.RunningNative) {
835 Object o = Reflection.obj_trav.getStaticFieldValue(f);
836 if (o == null) return 0L;
837 return ((Float)o).floatValue();
838 }
839 return Float.intBitsToFloat(getstatic_I(f));
840 }
841 public double getstatic_D(jq_StaticField f) {
842 Assert._assert(f.getType() == jq_Primitive.DOUBLE);
843 if (!jq.RunningNative) {
844 Object o = Reflection.obj_trav.getStaticFieldValue(f);
845 if (o == null) return 0L;
846 return ((Double)o).doubleValue();
847 }
848 return Double.longBitsToDouble(getstatic_L(f));
849 }
850 public Object getstatic_A(jq_StaticField f) {
851 Assert._assert(f.getType().isReferenceType() && !f.getType().isAddressType());
852 if (!jq.RunningNative) return Reflection.obj_trav.getStaticFieldValue(f);
853 return ((HeapAddress) f.getAddress().peek()).asObject();
854 }
855 public Address getstatic_P(jq_StaticField f) {
856 Assert._assert(f.getType().isAddressType());
857 if (!jq.RunningNative) {
858 Address a = (Address)Reflection.obj_trav.getStaticFieldValue(f);
859
860 return a;
861 }
862 return f.getAddress().peek();
863 }
864 public boolean getstatic_Z(jq_StaticField f) {
865 Assert._assert(f.getType() == jq_Primitive.BOOLEAN);
866 if (!jq.RunningNative) {
867 Object o = Reflection.obj_trav.getStaticFieldValue(f);
868 if (o == null) return false;
869 return ((Boolean)o).booleanValue();
870 }
871 return f.getAddress().peek4()!=0;
872 }
873 public byte getstatic_B(jq_StaticField f) {
874 Assert._assert(f.getType() == jq_Primitive.BYTE);
875 if (!jq.RunningNative) {
876 Object o = Reflection.obj_trav.getStaticFieldValue(f);
877 if (o == null) return 0;
878 return ((Byte)o).byteValue();
879 }
880 return f.getAddress().peek1();
881 }
882 public short getstatic_S(jq_StaticField f) {
883 Assert._assert(f.getType() == jq_Primitive.SHORT);
884 if (!jq.RunningNative) {
885 Object o = Reflection.obj_trav.getStaticFieldValue(f);
886 if (o == null) return 0;
887 return ((Short)o).shortValue();
888 }
889 return f.getAddress().peek2();
890 }
891 public char getstatic_C(jq_StaticField f) {
892 Assert._assert(f.getType() == jq_Primitive.CHAR);
893 if (!jq.RunningNative) {
894 Object o = Reflection.obj_trav.getStaticFieldValue(f);
895 if (o == null) return 0;
896 return ((Character)o).charValue();
897 }
898 return (char)f.getAddress().peek4();
899 }
900 public void putstatic_I(jq_StaticField f, int v) {
901 Assert._assert(f.getType() == jq_Primitive.INT);
902 if (!jq.RunningNative) {
903 Reflection.obj_trav.putStaticFieldValue(f, new Integer(v));
904 return;
905 }
906 f.getDeclaringClass().setStaticData(f, v);
907 }
908 public void putstatic_L(jq_StaticField f, long v) {
909 Assert._assert(f.getType() == jq_Primitive.LONG);
910 if (!jq.RunningNative) {
911 Reflection.obj_trav.putStaticFieldValue(f, new Long(v));
912 return;
913 }
914 f.getDeclaringClass().setStaticData(f, v);
915 }
916 public void putstatic_F(jq_StaticField f, float v) {
917 Assert._assert(f.getType() == jq_Primitive.FLOAT);
918 if (!jq.RunningNative) {
919 Reflection.obj_trav.putStaticFieldValue(f, new Float(v));
920 return;
921 }
922 f.getDeclaringClass().setStaticData(f, v);
923 }
924 public void putstatic_D(jq_StaticField f, double v) {
925 Assert._assert(f.getType() == jq_Primitive.DOUBLE);
926 if (!jq.RunningNative) {
927 Reflection.obj_trav.putStaticFieldValue(f, new Double(v));
928 return;
929 }
930 f.getDeclaringClass().setStaticData(f, v);
931 }
932 public void putstatic_A(jq_StaticField f, Object v) {
933 Assert._assert(v == null || TypeCheck.isAssignable(jq_Reference.getTypeOf(v), f.getType()));
934 Assert._assert(!f.getType().isAddressType());
935 if (!jq.RunningNative) {
936 Reflection.obj_trav.putStaticFieldValue(f, v);
937 return;
938 }
939 f.getDeclaringClass().setStaticData(f, v);
940 }
941 public void putstatic_P(jq_StaticField f, Address v) {
942 Assert._assert(f.getType().isAddressType());
943 if (!jq.RunningNative) {
944 Reflection.obj_trav.putStaticFieldValue(f, v);
945 return;
946 }
947 f.getDeclaringClass().setStaticData(f, v);
948 }
949 public void putstatic_Z(jq_StaticField f, boolean v) {
950 Assert._assert(f.getType() == jq_Primitive.BOOLEAN);
951 if (!jq.RunningNative) {
952 Reflection.obj_trav.putStaticFieldValue(f, Convert.getBoolean(v));
953 return;
954 }
955 f.getDeclaringClass().setStaticData(f, v?1:0);
956 }
957 public void putstatic_B(jq_StaticField f, byte v) {
958 Assert._assert(f.getType() == jq_Primitive.BYTE);
959 if (!jq.RunningNative) {
960 Reflection.obj_trav.putStaticFieldValue(f, new Byte(v));
961 return;
962 }
963 f.getDeclaringClass().setStaticData(f, (int)v);
964 }
965 public void putstatic_S(jq_StaticField f, short v) {
966 Assert._assert(f.getType() == jq_Primitive.SHORT);
967 if (!jq.RunningNative) {
968 Reflection.obj_trav.putStaticFieldValue(f, new Short(v));
969 return;
970 }
971 f.getDeclaringClass().setStaticData(f, (int)v);
972 }
973 public void putstatic_C(jq_StaticField f, char v) {
974 Assert._assert(f.getType() == jq_Primitive.CHAR);
975 if (!jq.RunningNative) {
976 Reflection.obj_trav.putStaticFieldValue(f, new Character(v));
977 return;
978 }
979 f.getDeclaringClass().setStaticData(f, (int)v);
980 }
981
982 public int arraylength(Object o) {
983 Assert._assert(getTypeOf(o).isArrayType());
984 if (!jq.RunningNative) return Array.getLength(o);
985 return HeapAddress.addressOf(o).offset(joeq.Allocator.ObjectLayout.ARRAY_LENGTH_OFFSET).peek4();
986 }
987 public Object arrayload_A(Object[] o, int i) {
988 if (!jq.RunningNative) return Reflection.obj_trav.mapValue(o[i]);
989 return o[i];
990 }
991 public Address arrayload_R(Address[] o, int i) {
992 return o[i];
993 }
994
995 public void registerNullStaticFields(Set s) {
996 s.add(_declaredFieldsCache);
997 s.add(_declaredMethodsCache);
998 }
999
1000 public void initialize() {
1001 _class = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Runtime/ReflectionImpl;");
1002 _declaredFieldsCache = _class.getOrCreateStaticField("declaredFieldsCache", "Ljava/util/HashMap;");
1003 _declaredMethodsCache = _class.getOrCreateStaticField("declaredMethodsCache", "Ljava/util/HashMap;");
1004 }
1005
1006 public static jq_Class _class;
1007 public static jq_StaticField _declaredFieldsCache;
1008 public static jq_StaticField _declaredMethodsCache;
1009 }